﻿using Max.PH6_2006A.LowCode.DataAccess;
using Max.PH6_2006A.LowCode.Domain;
using Max.PH6_2006A.LowCode.DTO;
using Max.PH6_2006A.LowCode.IService;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace Max.PH6_2006A.LowCode.API.Controllers
{
    /// <summary>
    /// 
    /// </summary>
    [Route("rbac/user")]
    [ApiController]
    //[Authorize]
    public class SystemUserController : BaseCRUDController<SystemUser, SystemUserInputDto, SystemUserOutputDto>
    {
        ISystemUserService _service;
        Microsoft.AspNetCore.Hosting.IWebHostEnvironment _host;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="service"></param>
        public SystemUserController(ISystemUserService service, Microsoft.AspNetCore.Hosting.IWebHostEnvironment host) : base(service)
        {
            _service = service;
            _host = host;
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        [HttpPost("login")]
        [AllowAnonymous]
        public async Task<IActionResult> LoginAsync(SystemUserLoginDto user)
        {
            DTO.ApiResultReturnDto dto = new();

            var result = await _service.LoginAsync(user);
            if (!result.Item1)
            {
                dto.Code = ApiResultReturnCode.Failed;
                dto.Message = result.Item3;
                return BadRequest(dto);
            }
            dto.Data = result.Item2;
            dto.Message = result.Item3;

            return Ok(dto);
        }

        /// <summary>
        /// 获取用户能访问的菜单
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet("getmenu")]
        public async Task<IActionResult> GetMenuByUserIdAsync(string id)
        {
            DTO.ApiResultReturnDto dto = new();

            var list = await _service.GetMenuByUserIdAsync(id);

            //一个用户有多个角色，角色之间拥有的菜单可能会重复，所以需要去重
            list = list.Where(x => !string.IsNullOrEmpty(x.Name)).DistinctBy(x => { return x.Id; }); //.DistinctBy(x => { return x.Id.ToString(); });

            dto.Data = RecursionMenu(list);

            return Ok(dto);
        }

        //这个递归菜单，在菜单列表也可以用到
        /// <summary>
        /// 递归获取层级菜单（组合成前台vue-menu需要的数据格式）
        /// </summary>
        /// <param name="data">所有数据的数据源，不用反复去连接数据库</param>
        /// <param name="id"></param>
        /// <returns></returns>
        private List<dynamic> RecursionMenu(IEnumerable<SystemMenu> data, string id = "")
        {
            var d = data.Where(x => Convert.ToString(x.FatherId) == id).ToList();

            List<dynamic> result = new();
            d.ForEach(p =>
            {
                var c = RecursionMenu(data, p.Id.ToString());
                result.Add(
                    new
                    {
                        name = p.Name,
                        url = p.Url,
                        children = c ?? null
                    });
            });
            return result;
        }


        /// <summary>
        /// 下载员工导入模板文件
        /// </summary>
        /// <returns></returns>
        [HttpGet("download")]
        public async Task<IActionResult> DownloadFileAsync()
        {
            var wwwroot = _host.WebRootPath;
            string filePath = Path.Combine(wwwroot, "template/employee(template).xlsx");
            if (!System.IO.File.Exists(filePath))
                return BadRequest(new { code = 500, message = "模板文件不存在" });

            var ms = await System.IO.File.ReadAllBytesAsync(filePath);
            return File(ms, "application/octet-stream", $"{System.DateTime.Now.ToString("yyyyMMdd")}.xlsx");
        }


        /// <summary>
        /// 显示所有用户（带角色）
        /// </summary>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("query/pages/dynamic")]
        public new async Task<IActionResult> QueryAsync(int pageIndex, int pageSize)
        {

            DTO.ApiResultReturnDto dto = new();

            //1、参数判断
            if (pageIndex <= 0) pageIndex = 1;
            if (pageSize <= 0) pageSize = 10;

            //2、调用业务(这数据包含了所有用户及用户对应的角色名称)
            string sql = "select u.*,r.[Name] as RoleName from SystemUser u ";
            sql += "left join SystemUserRole ur on u.id = ur.UserID ";
            sql += "left join SystemRole r on ur.RoleID = r.ID";
            var temp = await _service.QueryDynamicAsync(pageIndex, pageSize, sql);  //获取符合条件的数据

            var list = temp.Item1;
            int total = temp.Item2; //所有符合条件的记录数
            //过滤用户列表
            var userList = list.DistinctBy(x => x.LoginName).ToList();

            //将这些数据中，把角色名称包含进去
            var newData = from a in userList
                          select new
                          {
                              a.ID,
                              a.Statue,
                              a.LoginName,
                              a.CreatedTime,
                              a.NickName,
                              RoleItems = list.Where(x => x.LoginName.Equals(a.LoginName) && x.RoleName != null).Select(x => x.RoleName) ?? null
                          };


            dto.Data = new { items = newData, total };


            //3、统一返回值
            return Ok(dto);
        }


        /// <summary>
        /// 用户配置角色
        /// </summary>
        /// <returns></returns>
        [HttpPost("config")]
        public async Task<IActionResult> UserConfigRoleAsync(List<SystemUserRole> userRoles)
        {
            DTO.ApiResultReturnDto dto = new();
            try
            {
                var result = await _service.UserConfigRoleAsync(userRoles);
                dto.Data = result;
            }
            catch (Exception ex)
            {
                dto.Code = ApiResultReturnCode.Failed;
                dto.Message = ex.Message;
            }
            return Ok(dto);
        }


        /// <summary>
        /// 添加用户的时候，同时添加这个用户拥有的多个角色
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost("and")]
        public async Task<IActionResult> InsertUserAndRole(InsertUserAndRoleDto param)
        //("用户的基本信息"，“用户对应的角色信息”)
        {
            DTO.ApiResultReturnDto dto = new();
            try
            {
                var result = await _service.InsertUserAndRoleAsync(param.user,param.userRole);
                dto.Data = result;
            }
            catch (Exception ex)
            {
                dto.Code = ApiResultReturnCode.Failed;
                dto.Message = ex.Message;
            }
            return Ok(dto);
        }
    }

    public class InsertUserAndRoleDto
    {
        public SystemUser user { get; set; }
        public List<SystemUserRole> userRole { get; set; }
    }
}
